home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-03-05 | 40.8 KB | 1,659 lines |
- /*
-
- Splitter 3.02
-
- This program can split files into several portions with a defined
- size or into a defined number of portions and can join them together
- again. It's main purpose is to write larger files and especially
- archives to disks. It was designed to compile under ANSI C and with
- some small modifications even under K&R C, and thus to run on any
- system which supports these.
-
- Version 1.0 on 18-October-1993 First reliable version.
- Version 1.1 on 18-October-1993 Replaced fclose()/fopen() by rewind().
- Version 1.2 on 24-November-1993 Works now with MSDOS systems;
- uses a buffer for join.
- Version 1.21 on 25-November-1993 Removed a small bug in the output.
- Version 2.0 on 22-September-1994 Added default sizes for filesystems.
- Uses Buffer for read/write. Uses fileheader
- for recognition and restauration.
- Version 2.1 on 31-March-1995 Options -r (splitted portion range, only
- with -p and -s) and -f (force overwrite)
- added. Bug removed when allocating smaller
- buffer. Multivolume joining enhanced.
- Version 3.0 on 22-February-1996 Complete rewrite. Enhanced command line
- parsing. Joining and multivolume via
- command name.
- Version 3.01 on 27-February-1996 Removed bug in splitpath generation.
- Version 3.02 on 5-March-1996 Removed another small bug in splitpath
- generation. Cleaned up usage info.
- Removed bug with empty files.
-
- This program was developed on an Amiga 1200 with the SAS/C development system
- and the GNU emacs editor, the UNIX adaptions were written on a Linux PC with
- gcc and emacs.
-
- Usage:
- Splitter [-n] [-d] [-l] [-m] [-g] [-f] [-q] [-j {<sources>} <destination>]
- [-h] [[-p <n>] [-s <n>[k|m]] [-s <disktype>] [-r <s> [<e>]] <file> <dir>]
-
- Joiner [-h] [-d] [-n] [-m] [-g] [-f] {<sources>} <destination>
-
- file the file to be splitted.
- dir directory where to put the splitted parts.
- sources source directories and files.
- destination destination path for joined file.
- -h show help.
- -n write/expect no header.
- -d MSDOS filename option: eight characters without dot.
- -l long filenames; resets the MSDOS switch.
- -m multivolume split/join; pause after each file.
- -g go ahead; resets the multivolume switch.
- -f overwrite existing files without asking (force).
- -q ask before overwriting files (query).
- -j join splitted parts.
- -p split into <n> portions.
- -s split into portions of <n> bytes size each.
- -r extract only portions in the range from s(tart) to e(nd).
-
- General:
- To get from Splitter, type the option "-h". Without options, Splitter
- will will do the standard action depending on the command name. If the
- command name contains the string "join" or "Join", splitter will react
- as if called with the option "-j". Otherwise it will split <source> to
- portions with the size of the first file system. If the command name
- contains "m" or "M", the multivolume option will be set automatically.
- If Splitter is compiled for a MSDOS platform, the MSDOS option is set.
- If the macro FORCE is defined, files are overwritten by default.
- To compile this program on a UNIX platform, the macro UNIX must be
- defined; for MSDOS computers, the MSDOS macro must be defined; the AMIGA
- macro is normally set by the compiler on the Amiga. The strings in
- the text define section may be changed to another language (or better
- english.. :-). If you do so, please let me have these.
-
- Splitting:
- There are two different approaches to split a file. The one produces
- the requested number of portion files with the same size each. Use
- "-p <n>" as options for this. The other produces several portions of
- the requested size. The size may be given directly in bytes, kbytes
- or mbytes. Use "-s <n>[k|m]" for this. Or it may be given as the
- destination disk type. Use option "-s <disktype>", where disktype may
- be any one of the filesystem sizes as listed by the option "-h". If
- no option is specified, the file is splitted as though <disktype> had
- beed set to the first in the list. <source> ist the path of the source
- file, <dir> is the path of the (optional) destination directory. The
- option "-d" makes the destination filenames msdos compliant. If "-n"
- is given, no header is written, the portions may be joined then by
- AmigaDOS' Join or unix' cat command. "-r <s> [<e>]" extracts only the
- portion <s> or the prtions <s> to <e>. "-m" lets Splitter pause before
- writing each portion so that a removable medium may be changed. If
- "-f" is specified, Splitter overwrites files without asking.
-
- Joining:
- Calling Splitter with a name that contains the word 'join' (i.e. via
- softlink) or with the option "-j" will create the original file from
- the portions. If the destination file name is given, only one source
- directory is required. This and any further source directory is scanned
- for the needed portions, and any source file is checked if it is a
- portion. If the destination is a directory at least one source file
- must be given. The destination file name is then derived from the
- header or from this file's name if no header can be found. The option
- "-d" makes Splitter look for source files with msdos compliant filenames.
- "-m" lets Splitter pause before reading the next directory. The option
- "-f" makes Splitter overwrite files without asking. If "-n" is given,
- Splitter does not look for headers.
-
- DISCLAIMER:
- I am in no way responsible for any problems that arise directly or
- indirectly from the use of this program.
-
- Copyright notice:
- This is freeware. You may give this program to anyone you like and
- upload it to any mailbox, bulletin board or software server or include
- it on any public domain distribution on disk or on CD-ROM as long as
- you charge only a small fee for medium and copy and leave this file as
- it is. But you may not use this program for commercial purposes without
- prior written permission from me. You may not distribute changed
- versions of this program.
- If you have any ideas how to improve this program, please mail
- them to me. My mail address is included in the info #define.
-
- The author:
- I'm a student of computer science at the university of Tuebingen,
- Germany. If you like this program, please let me know. This program
- was intentionally made freeware. If you have written some shareware
- program, be so kind to let me have it for free if you use Splitter
- frequently.
- Please feel free to mail me any ideas concerning this program.
-
- My address:
- Martin Schlodder
- Uhlandstr. 18
- D-72336 Balingen
-
- EMAIL:
- schlodder@student.uni-tuebingen.de
- */
-
- /*
- Select the appropriate #define statement or use the define compiler
- option to choose the system on which you want to compile this source.
- These defines are neccessary to select the right path seperators.
- If you know any more file systems, please mail their path rules to
- me and i will include them.
- #define AMIGA
- #define MSDOS
- #define UNIX
- */
-
- /*
- Some more filesystems for the Amiga may be enabled by the following:
- #define AMIFS Amiga file systems
- #define AMIDC AmigaOS 3.0 DirCache file system
- #define AMIPFS PFS file system
- #define AMIDS DiskSpare device
- */
-
- /*
- If FORCE is defined, Splitter does not ask before overwriting files
- by default.
- #define FORCE
- */
-
- /*
- If DBUG is defined, each function will print it's arguments.
- #define DBUG
- */
-
- /*
- The following #define block contains every text printed by Splitter.
- The messages are collected to make translation easier.
- */
- /*
- Info is printed if the -h option is set.
- */
- #define info1 "\nSplitter V3.02 on March 5, 1996\n\
- (c)1993-1996 by Martin Schlodder\n\n"
- #define info1s info1 "\
- Usage: %s [-n] [-d] [-l] [-m] [-g] [-f] [-q] [-j {<sources>} <destination>]\n\
- [-h] [[-p <n>] [-s <n>[k|m]] [-s <disktype>] [-r <s> [<e>]] <file> <dir>]\n\
- file\t\tthe file to be splitted.\n\
- dir\t\tdirectory where tp put the splitted parts.\n\
- sources\tsource directories and files.\n\
- destination\tdestination path for joined file.\n\
- -h\t\tshow this help page.\n\
- -n\t\twrite/expect no header.\n\
- -d\t\tMSDOS filename option: eight chars without dot.\n\
- -l\t\tlong filenames; resets the MSDOS switch.\n\
- -m\t\tmultivolume split/join; pause after each file.\n\
- -g\t\tgo ahead; resets the multivolume switch.\n\
- -f\t\toverwrite existing files fithout asking (force).\n\
- -q\t\task before overwriting files (query).\n\
- -j\t\tjoin splitted parts.\n\
- -p\t\tsplit into <n> portions.\n\
- -s\t\tsplit into portions of <n> [k|m]bytes size each.\n\
- -r\t\textract only portions in the range from s(tart) to e(end).\n\
- If neither -j nor -p nor -s are set, Splitter will create portions of\n\
- the size from the first line of the list below.\n\n\
- [Press <Return> to continue]"
- #define info1j info1 "\
- Usage: %s [-h] [-n] [-d] [-l] [-m] [-g] [-f] [-q] {<sources>} <destination>\n\
- sources\tsource directories and files.\n\
- destination\tdestination path for joined file.\n\
- -h\t\tshow this help page.\n\
- -n\t\twrite/expect no header.\n\
- -d\t\tMSDOS filename option: eight chars without dot.\n\
- -l\t\tlong filenames; resets the MSDOS switch.\n\
- -m\t\tmultivolume split/join; pause after each file.\n\
- -g\t\tgo ahead; resets the multivolume switch.\n\
- -f\t\toverwrite existing files fithout asking (force).\n\
- -q\t\task before overwriting files (query).\n"
- #define info2 "\nFile system sizes: (for <disktype>)"
- #define main_fs " %-12s - %7d bytes - %s."
- #define main_end "\n\
- Address:\n\
- Martin Schlodder\n\
- Uhlandstr. 18\n\
- D-72336 Balingen\n\n\
- Internet:\n\
- schlodder@zdv.uni-tuebingen.de\n"
-
- /*
- This text is shown before waiting for a key press when the -w option is set.
- */
- #define make_multi_part "Please insert volume and press <Return>"
-
- /*
- This text is shown when a file will be overwritten and the -q option is set.
- The key definition is the positive answer (overwrite).
- */
- #define query_overwrite_a "Overwrite file \"%s\"? [y(es)|n(o)|a(ll)] "
- #define query_overwrite "Overwrite file \"%s\"? [y(es)|n(o)] "
- #define query_yes 'y'
- #define query_all 'a'
-
- /*
- These texts are used to print the success message after joining.
- */
- #define join_heads "Headers found."
- #define join_Joined "Joined \"%s\""
- #define join_file ", \"%s\""
- #define join_to " to \"%s\"."
- #define multi_join "Joined one portion to \"%s\"."
- #define multi_join_n "Joined %d portions to \"%s\"."
-
- /*
- These texts are used to print the success message after splitting.
- */
- #define split_Splitted "Splitted \"%s\" into "
- #define split_portion "one portion of %d bytes."
- #define split_portions "%d portions of %d bytes."
- #define split_portion_and "one portion of %d bytes and\none portion of %d bytes."
- #define split_portions_and "%d portions of %d bytes and\none portion of %d bytes."
- #define split_Extract "Extracted portions %d to %d."
- #define split_Extract_one "Extracted portion %d."
-
- /*
- These are the error messages.
- */
- #define err_bad_dest "Destination must be a directory."
- #define err_bad_file "Bad file name definition."
- #define err_bad_files "No portions found."
- #define err_bad_num "Bad number specification for option '-p'."
- #define err_bad_range "Range parameters illegal."
- #define err_bad_size "Bad size specification for option '-s'."
- #define err_file_empty "Source file is empty."
- #define err_no_args "Need a file name to split. Type '%s -h' for help."
- #define err_no_file "Need a file name."
- #define err_no_files "Destination path or portion paths must contain a filename."
- #define err_no_mem "Not enough memory."
- #define err_no_name "The source files must have a splitter format name\nif joining portions without header."
- #define err_no_portion "Can't find any files to join."
- #define err_no_source "Need a source directory or source files to join."
- #define err_open_dest "Couldn't open \"%s\" as destination."
- #define err_open_dir "Could't read directory \"%s\"."
- #define err_open_source "Couldn't open \"%s\" as source."
- #define err_portion_missing "Can't find portion %d."
- #define err_read "Error while reading."
- #define err_read_head "Error while reading header."
- #define err_seek "Error while seeking file."
- #define err_unknown_option "Unknown option '-%c'."
- #define err_write "Error while writing."
- #define err_write_abort "File not overwritten. Execution aborted."
- #define err_write_head "Error while writing header."
- #define err_wrong_portion "Portion number differs from header number."
-
- /*
- These are the warning messages.
- */
- #define warn_size "WARNING! Source file size changed."
- #define warn_t_size "WARNING! Destination file size changed."
- #define warn_files_missing "WARNING! Some portions are missing."
- #define warn_n_files_missing "WARNING! %d portions are missing."
- #define warn_one_file_missing "WARNING! One portion is missing."
- #define warn_wrong_portion "WARNING! Wrong portion in source file list."
-
- /*
- These are the known file systems.
- */
- struct fs_item
- {
- char *name;
- unsigned long size;
- char *desc;
- }fs[]={
- {"msd-dd",730112,"MSDOS Double Density Disk"},
- {"msd-hd",1457664,"MSDOS High Density Disk"},
- #ifdef AMIFS
- {"amiofs-dd",844240,"Amiga Double Density Disk, OldFileSystem"},
- {"amiofs-hd",1691408,"Amiga High Density Disk, OldFileSystem"},
- {"amiffs-dd",885760,"Amiga Double Density Disk, FastFileSystem"},
- {"amiffs-hd",1774592,"Amiga High Density Disk, FastFileSystem"},
- #ifdef AMIDC
- {"amiofsdc-dd",843752,"Amiga Double Density Disk, OldFileSystem, DirCache"},
- {"amiofsdc-hd",1690920,"Amiga High Density Disk, OldFileSystem, DirCache"},
- {"amiffsdc-dd",884736,"Amiga Double Density Disk, FastFileSystem, DirCache"},
- {"amiffsdc-hd",1774080,"Amiga High Density Disk, FastFileSystem, DirCache"},
- #endif
- #ifdef AMIPFS
- {"amipfs-dd",896512,"Amiga Double Density Disk, ProfFileSystem"},
- {"amipfs-hd",1797632,"Amiga High Density Disk, ProfFileSystem"},
- #endif
- #ifdef AMIDS
- {"amidsofs-dd",844240,"Amiga Double Density Disk, DiskSpare, OldFileSystem"},
- {"amidsofs-hd",1691408,"Amiga High Density Disk, DiskSpare, OldFileSystem"},
- {"amidsffs-dd",885760,"Amiga Double Density Disk, DiskSpare, FastFileSystem"},
- {"amidsffs-hd",1774592,"Amiga High Density Disk, DiskSpare, FastFileSystem"},
- #ifdef AMIDC
- {"amidsofsdc-dd",843752,"Amiga Double Density Disk, DiskSpare, OldFileSystem, DirCache"},
- {"amidsofsdc-hd",1690920,"Amiga High Density Disk, DiskSpare, OldFileSystem, DirCache"},
- {"amidsffsdc-dd",884736,"Amiga Double Density Disk, DiskSpare, FastFileSystem, DirCache"},
- {"amidsffsdc-hd",1774080,"Amiga High Density Disk, DiskSpare, FastFileSystem, DirCache"},
- #endif
- #ifdef AMIPFS
- {"amidspfs-dd",1003008,"Amiga Double Density Disk, DiskSpare, ProfFileSystem"},
- {"amidspfs-hd",2010624,"Amiga High Density Disk, DiskSpare, ProfFileSystem"},
- #endif
- #endif
- #endif
- };
-
- /*
- The maximal length of an input string:
- */
- #define STRMAX 256
-
- /*
- Standard includes.
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <dirent.h>
-
- /*
- Each file is preceded with a fileheader (if the -n option was not set)
- consisting of the following structure:
- */
- #define hd_magic "Splitter"
- #define hd_name (8+4+8+4+8+1)
- #define hd_namesize 31
- struct header{
- short number;
- unsigned long size;
- short tnumber;
- unsigned long tsize;
- char name[hd_namesize];
- };
- #define hd_size (hd_name+hd_namesize)
-
- /*
- This is the version information for the Amiga's shell command 'Version'.
- */
- #ifdef AMIGA
- char *amiga_version="$VER: Splitter 3.02 (5.3.96) ©1993-1996 by Martin Schlodder";
- #endif
-
- /*
- The only global variables are some status flags, the range parameters
- and a string buffer.
- */
- int rstart,rend,msdos,head,multi,query;
- char buf[STRMAX];
-
- /*
- int WriteHead(FILE *fh,header *hd)
- fh: File handle.
- hd: Pointer to header structure.
- returns: Nonzero if error occurs.
- This function writes the header from the the structure hd into the file fh.
- */
- int WriteHead(FILE *fh,struct header *hd){
- char hdbuf[hd_size];
- #ifdef DBUG
- printf("\nWriteHead($%08X,{%d,%lu,%d,%lu,\"%s\"});\n",fh,hd->number,hd->size,hd->tnumber,hd->tsize,hd->name);
- #endif
- sprintf(hdbuf,"%s%4X%8X%4X%8X ",hd_magic,hd->number,hd->size,hd->tnumber,hd->tsize);
- memcpy(hdbuf+hd_name,hd->name,hd_namesize);
- if(fwrite(hdbuf,1,hd_size,fh)!=hd_size)
- return(1);
- return(0);
- }
-
- /*
- int ReadHead(FILE *fh,header *hd)
- fh: File handle.
- hd: Pointer to header structure.
- returns: Nonzero if error occurs.
- This function reads the header from the file fh into the structure hd.
- */
- int ReadHead(FILE *fh,struct header *hd){
- char buf[hd_size];
- #ifdef DBUG
- printf("\nReadHead($%x,$%x);\n",fh,hd);
- #endif
- if(fread(buf,1,hd_size,fh)!=hd_size){
- #ifdef DBUG
- puts("\nReadHead() -> 1");
- #endif
- return(1);
- }
- if(4!=sscanf(buf,hd_magic "%4hx%8lx%4hx%8lx ",&hd->number,&hd->size,&hd->tnumber,&hd->tsize)){
- #ifdef DBUG
- puts("\nReadHead() -> 1");
- #endif
- return(1);
- }
- memcpy(hd->name,buf+hd_name,hd_namesize);
- #ifdef DBUG
- printf("\nReadHead() -> 0 hd: {%d,%lu,%d,%lu,\"%s\"}\n",hd->number,hd->size,hd->tnumber,hd->tsize,hd->name);
- #endif
- return(0);
- }
-
- /*
- Join(char *dest,char *paths[],int num)
- dest: Destination path or empty string.
- paths: Array of source paths.
- num: Number of source paths.
- Global:
- msdos: -use- Filenames of portions are supposed to be MSDOS
- compatible (eight characters, no dots).
- head: -use- Try to find header.
- query: -use- Ask before overwriting existing files.
- multi: -use- Join from multiple volumes using MultiJoin().
- Calls:
- ReadHead: Read header from portion file.
- Join() joins the portions to the original file. Dest is a directory or
- file, paths is NULL if num is 0. Frees 'paths' allocated by main().
- */
- void Join(char *dest,char **paths,int num){
- int i,j,k,fnum,dnum,dir,tnum,chunks;
- unsigned long tsize,size,asize,read,written,twritten;
- int *isdir,*findex,*jindex;
- char *sbuf,*tbuf,*dfile,*pos,*name;
- char **sfiles,**files, **dirs;
- FILE *source,*dhand;
- DIR *dfd;
- struct header hd;
- #ifdef DBUG
- printf("\nJoin(\"%s\",({",dest);
- for(i=0;i<num-1;i++)
- printf("\"%s\",",paths[i]);
- if(num)
- printf("\"%s\"",paths[i]);
- printf("}),%d); Uses: multi(%s), head(%s), query(%s), msdos(%s)\n",num,multi?"TRUE":"FALSE",head?"TRUE":"FALSE",query?"TRUE":"FALSE",msdos?"TRUE":"FALSE");
- #endif
- dir=0;
- if(!num){
- puts(err_no_source);
- free(paths);
- exit(EXIT_FAILURE);
- }
- if(dfd=opendir(dest)){
- closedir(dfd);
- dir=1;
- }
- if(!(isdir=(int *)malloc(num*sizeof(int)))){
- puts(err_no_mem);
- free(paths);
- exit(EXIT_FAILURE);
- }
- for(i=dnum=0;i<num;i++)
- if(dfd=opendir(paths[i])){
- closedir(dfd);
- isdir[i]=1;
- dnum++;
- }
- else
- isdir[i]=0;
- fnum=num-dnum;
- files=dirs=0;
- if(dnum && !(dirs=(char **)malloc(dnum*sizeof(char *)))){
- puts(err_no_mem);
- free(paths);
- free(isdir);
- exit(EXIT_FAILURE);
- }
- if(fnum && !(files=(char **)malloc(fnum*sizeof(char *)))){
- puts(err_no_mem);
- free(paths);
- free(isdir);
- free(dirs);
- exit(EXIT_FAILURE);
- }
- for(i=dnum=fnum=0;i<num;i++)
- if(isdir[i])
- dirs[dnum++]=paths[i];
- else
- files[fnum++]=paths[i];
- free(paths);
- free(isdir);
- size=0;
- tnum=0;
- if(fnum){
- if(!(findex=(int *)malloc(fnum*sizeof(int)))){
- puts(err_no_mem);
- free(files);
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- if(!(source=fopen(files[0],"rb"))){
- printf(err_open_source "\n",files[0]);
- free(findex);
- free(files);
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- if(head && ReadHead(source,&hd))
- head=0;
- if(head){
- size=hd.size>size?hd.size:size;
- findex[0]=hd.number;
- }
- else{
- if(fseek(source,0L,SEEK_END)){
- puts(err_seek);
- fclose(source);
- free(findex);
- free(files);
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- size=(asize=ftell(source))>size?asize:size;
- }
- fclose(source);
- for(i=1;i<fnum;i++){
- if(!(source=fopen(files[i],"rb"))){
- printf(err_open_source "\n",files[i]);
- free(findex);
- free(files);
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- if(head){
- if(ReadHead(source,&hd)){
- puts(err_read_head);
- fclose(source);
- free(findex);
- free(files);
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- size=hd.size>size?hd.size:size;
- findex[i]=hd.number;
- }
- else{
- if(fseek(source,0L,SEEK_END)){
- puts(err_seek);
- fclose(source);
- free(findex);
- free(files);
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- size=(asize=ftell(source))>size?asize:size;
- }
- fclose(source);
- }
- if(head){
- tnum=hd.tnumber;
- tsize=hd.tsize;
- }
- else{
- for(i=0;i<fnum;i++)
- tnum=(findex[i]=atoi(files[i]+strlen(files[i])-3))>tnum?findex[i]:tnum;
- }
- if(!(jindex=(int *)calloc(tnum,sizeof(int)))){
- puts(err_no_mem);
- free(findex);
- free(files);
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- for(i=0;i<tnum;i++)
- for(j=0;j<fnum;j++)
- if(findex[j]==i+1){
- jindex[i]=j+1;
- break;
- }
- free(findex);
- if(dir){
- #ifndef UNIX
- if(i=strlen(dest)){
- #ifdef AMIGA
- if(dest[--i]=='/' || dest[i]==':')
- j=0;
- #else
- if(dest[--i]=='\\' || dest[i]==':')
- j=0;
- #endif
- else
- j=1;
- }
- else
- j=0;
- if(head){
- if(!(dfile=(char *)malloc(strlen(hd.name)+strlen(dest)+j+1))){
- puts(err_no_mem);
- free(jindex);
- free(files);
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- #ifdef AMIGA
- sprintf(dfile,"%s%s%s",dest,j?"/":"",hd.name);
- #else
- sprintf(dfile,"%s%s%s",dest,j?"\\":"",hd.name);
- #endif
- }
- else{
- #ifdef AMIGA
- if(!(pos=strrchr(files[0],'/')) && !(pos=strrchr(files[0],':')))
- pos=files[0];
- #else
- if(!(pos=strrchr(files[0],'\\')) && !(pos=strrchr(files[0],':')))
- pos=files[0];
- #endif
- if(!(dfile=(char *)malloc(strlen(pos)+strlen(dest)+j-3))){
- puts(err_no_mem);
- free(jindex);
- free(files);
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- #ifdef AMIGA
- sprintf(dfile,"%s%s%.*s",dest,j?"/":"",strlen(pos)-4,pos);
- #else
- sprintf(dfile,"%s%s%.*s",dest,j?"\\":"",strlen(pos)-4,pos);
- #endif
- }
- #else
- if(head){
- if(!(dfile=(char *)malloc(strlen(hd.name)+strlen(dest)+1))){
- puts(err_no_mem);
- free(jindex);
- free(files);
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- sprintf(dfile,"%s/%s",dest,hd.name);
- }
- else{
- if(!(pos=strrchr(files[0],'/')))
- pos=files[0];
- if(!(dfile=(char *)malloc(strlen(pos)+strlen(dest)-3))){
- puts(err_no_mem);
- free(jindex);
- free(files);
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- sprintf(dfile,"%s/%.*s",dest,strlen(pos)-4,pos);
- }
- #endif
- }
- else
- dfile=dest;
- }
- else{
- if(dir){
- puts(err_no_files);
- free(dirs);
- exit(EXIT_FAILURE);
- }
- dfile=dest;
- }
- if(query && (dhand=fopen(dfile,"rb"))){
- fclose(dhand);
- printf(query_overwrite,dfile);
- gets(buf);
- if(buf[0]!=query_yes){
- puts(err_write_abort);
- if(fnum){
- free(jindex);
- free(files);
- }
- if(dnum)
- free(dirs);
- exit(EXIT_FAILURE);
- }
- }
- if(fnum && head){
- if(!(name=(char *)malloc(strlen(hd.name)+1))){
- puts(err_no_mem);
- free(jindex);
- free(files);
- if(dnum)
- free(dirs);
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- strcpy(name,hd.name);
- }
- else{
- #ifdef AMIGA
- if((pos=strrchr(dfile,'/')) || (pos=strrchr(dfile,':')))
- pos++;
- #endif
- #ifdef MSDOS
- if((pos=strrchr(dfile,'\\')) || (pos=strrchr(dfile,':')))
- pos++;
- #endif
- #ifdef UNIX
- if(pos=strrchr(dfile,'/'))
- pos++;
- #endif
- else
- pos=dfile;
- if(!(name=(char *)malloc(strlen(pos)+1))){
- puts(err_no_mem);
- if(fnum){
- free(jindex);
- free(files);
- }
- if(dnum)
- free(dirs);
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- strcpy(name,pos);
- }
- if(msdos){
- if(pos=strchr(name,'.'))
- pos[0]='\0';
- if(strlen(name)>8)
- name[8]='\0';
- }
- if(dnum){
- if(!(sfiles=(char **)malloc(dnum*sizeof(char *)))){
- puts(err_no_mem);
- free(name);
- if(fnum){
- free(jindex);
- free(files);
- }
- free(dirs);
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- for(i=0;i<dnum;i++){
- #ifndef UNIX
- if(k=strlen(dirs[i])){
- #ifdef AMIGA
- if(dirs[i][--k]=='/' || dirs[i][k]==':')
- j=0;
- #else
- if(dirs[i][--k]=='\\' || dirs[i][k]==':')
- j=0;
- #endif
- else
- j=1;
- }
- else
- j=0;
- if(!(sfiles[i]=(char *)malloc(strlen(dirs[i])+j+strlen(name)+1))){
- puts(err_no_mem);
- free(name);
- for(j=0;j<i;j++)
- free(sfiles[j]);
- free(sfiles);
- if(fnum){
- free(jindex);
- free(files);
- }
- free(dirs);
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- #ifdef AMIGA
- sprintf(sfiles[i],"%s%s%s",dirs[i],j?"/":"",name);
- #else
- sprintf(sfiles[i],"%s%s%s",dirs[i],j?"\\":"",name);
- #endif
- #else
- if(!(sfiles[i]=(char *)malloc(strlen(dirs[i])+strlen(name)+2))){
- puts(err_no_mem);
- free(name);
- for(j=0;j<i;j++)
- free(sfiles[j]);
- free(sfiles);
- if(fnum){
- free(jindex);
- free(files);
- }
- free(dirs);
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- sprintf(sfiles[i],"%s/%s",dirs[i],name);
- #endif
- }
- free(dirs);
- }
- if(!fnum){
- if(multi){
- puts(make_multi_part);
- gets(buf);
- }
- for(i=0;i<dnum;i++){
- if(!(sbuf=malloc(strlen(sfiles[i])+5))){
- puts(err_no_mem);
- free(name);
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- exit(EXIT_FAILURE);
- }
- sprintf(sbuf,"%s.001",sfiles[i]);
- if(source=fopen(sbuf,"rb"))
- break;
- free(sbuf);
- }
- free(sbuf);
- if(!source){
- puts(err_no_portion);
- free(name);
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- exit(EXIT_FAILURE);
- }
- if(head && ReadHead(source,&hd))
- head=0;
- if(head){
- tnum=hd.tnumber;
- tsize=hd.tsize;
- size=hd.size;
- }
- else{
- tnum=1;
- if(fseek(source,0L,SEEK_END)){
- puts(err_seek);
- fclose(source);
- free(name);
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- exit(EXIT_FAILURE);
- }
- size=ftell(source);
- }
- fclose(source);
- }
- if(!(dhand=fopen(dfile,"wb"))){
- printf(err_open_dest "\n",dfile);
- free(name);
- if(dnum){
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- }
- if(fnum){
- free(jindex);
- free(files);
- }
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- if(!size){
- puts(err_file_empty);
- free(name);
- if(dnum){
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- }
- if(fnum){
- free(jindex);
- free(files);
- }
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- if(!(tbuf=(char *)malloc(asize=size))){
- while(asize>10000 && !tbuf)
- tbuf=(char *)malloc(asize=(asize+1)/2);
- if(!tbuf){
- puts(err_no_mem);
- fclose(dhand);
- free(name);
- if(dnum){
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- }
- if(fnum){
- free(jindex);
- free(files);
- }
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- }
- chunks=(size+asize-1)/asize;
- if(!multi && head)
- puts(join_heads);
- for(i=0,twritten=0;!head||i<tnum;i++){
- if(fnum && i<tnum && (j=jindex[i])>0){
- if(!(source=fopen(files[j-1],"rb"))){
- printf(err_open_source "\n",files[j-1]);
- fclose(source);
- fclose(dhand);
- free(tbuf);
- free(name);
- if(dnum){
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- }
- free(jindex);
- free(files);
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- if(!multi)
- if(i)
- printf(join_file,files[j-1]);
- else
- printf(join_Joined,files[j-1]);
- if(head && ReadHead(source,&hd)){
- puts(err_read_head);
- fclose(source);
- fclose(dhand);
- free(tbuf);
- free(name);
- if(dnum){
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- }
- free(jindex);
- free(files);
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- }
- else{
- if(!dnum){
- if(!head && i>=tnum)
- break;
- printf("\n" err_portion_missing "\n",i+1);
- fclose(dhand);
- free(tbuf);
- free(name);
- free(jindex);
- free(files);
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- if(multi && (i||fnum)){
- puts(make_multi_part);
- gets(buf);
- }
- for(j=0;j<dnum;j++){
- if(!(sbuf=malloc(strlen(sfiles[j])+5))){
- puts(err_no_mem);
- fclose(dhand);
- free(tbuf);
- free(name);
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- if(fnum){
- free(jindex);
- free(files);
- }
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- sprintf(sbuf,"%s.%03d",sfiles[j],i+1);
- if(source=fopen(sbuf,"rb"))
- break;
- free(sbuf);
- }
- if(source && !multi)
- if(i)
- printf(join_file,sbuf);
- else
- printf(join_Joined,sbuf);
- free(sbuf);
- if(!source){
- if(!head && i>=tnum)
- break;
- printf("\n" err_portion_missing "\n",i+1);
- fclose(dhand);
- free(tbuf);
- free(name);
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- if(fnum){
- free(jindex);
- free(files);
- }
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- if(head && ReadHead(source,&hd)){
- puts(err_read_head);
- fclose(source);
- fclose(dhand);
- free(tbuf);
- free(name);
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- if(fnum){
- free(jindex);
- free(files);
- }
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- }
- if(head && hd.number!=i+1){
- puts(err_wrong_portion);
- fclose(source);
- fclose(dhand);
- free(tbuf);
- free(name);
- if(dnum){
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- }
- if(fnum){
- free(jindex);
- free(files);
- }
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- for(j=0,written=0;j<chunks;j++){
- if(!(read=fread(tbuf,1,asize,source))){
- puts(err_read);
- fclose(source);
- fclose(dhand);
- free(tbuf);
- free(name);
- if(dnum){
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- }
- if(fnum){
- free(jindex);
- free(files);
- }
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- if(fwrite(tbuf,1,read,dhand)!=read){
- puts(err_write);
- fclose(source);
- fclose(dhand);
- free(tbuf);
- free(name);
- if(dnum){
- for(i=0;i<dnum;i++)
- free(sfiles[i]);
- free(sfiles);
- }
- if(fnum){
- free(jindex);
- free(files);
- }
- if(dir)
- free(dfile);
- exit(EXIT_FAILURE);
- }
- written+=read;
- }
- twritten+=written;
- fclose(source);
- if(head && hd.size!=written)
- puts(warn_size);
- }
- fclose(dhand);
- free(tbuf);
- free(name);
- if(dnum){
- for(j=0;j<dnum;j++)
- free(sfiles[j]);
- free(sfiles);
- }
- if(fnum){
- free(jindex);
- free(files);
- }
- if(multi){
- if(i-1)
- printf(multi_join_n "\n",i,dfile);
- else
- printf(multi_join "\n",dfile);
- }
- else
- printf(join_to "\n",dfile);
- if(dir)
- free(dfile);
- if(head){
- if(multi)
- puts(join_heads);
- if(twritten!=tsize)
- puts(warn_t_size);
- }
- exit(0);
- }
-
- /*
- Split(char *file,char *path,int num,unsigned long size)
- file: Source file.
- path: Destination path.
- num: Number of portions. Mutually exclusive with size.
- size: Size of the portions. Mutually exclusive with num.
- Global:
- rstart: -use- First protion to extract.
- rend: -use- Last Portion to extract.
- msdos: -use- Filenames of portions are made MSDOS compatible (eight
- characters, no dots).
- head: -use- Write header.
- multi: -use- Split to multiple volumes, waiting after each portion.
- query: -use- Ask before overwriting existing files.
- Calls:
- WriteHead: Write header to portion file.
- This function does the splitting. If Splitter was called with the -p
- command set, num is provided. If the -s command or no command was set
- (default size), size will be valid. file is always valid, path may be
- NULL.
- */
- void Split(char *file,char *path,int num,unsigned long size){
- int i,j,cnum;
- unsigned long tsize,csize,asize,rsize,rcsize,acsize;
- char *dfile,*dpath,*dbuf,*tbuf,*pos,*name;
- struct header hd;
- FILE *source,*dest;
- DIR *dfd;
- #ifdef DBUG
- printf("\nSplit(\"%s\",",file);
- if(path)
- printf("\"%s\",",path);
- else
- printf("0,");
- printf("%d,%lu); Uses: rstart(%d), rend(%d), msdos(%s), head(%s), multi(%s), query(%s)\n",num,size,rstart,rend,msdos?"TRUE":"FALSE",head?"TRUE":"FALSE",multi?"TRUE":"FALSE",query?"TRUE":"FALSE");
- #endif
- if(head){
- if(size)
- size=size-hd_size;
- for(i=0;i<hd_namesize;i++)
- hd.name[i]='\0';
- }
- if(dfd=opendir(file)){
- closedir(dfd);
- printf(err_open_source "\n",file);
- exit(EXIT_FAILURE);
- }
- if(!(source=fopen(file,"rb"))){
- printf(err_open_source "\n",file);
- exit(EXIT_FAILURE);
- }
- pos=0;
- #ifdef AMIGA
- if((name=strrchr(file,'/')) || (pos=strrchr(file,':')))
- if(pos)
- name=pos+1;
- else
- name++;
- #endif
- #ifdef MSDOS
- if((name=strrchr(file,'\\')) || (pos=strrchr(file,':')))
- if(pos)
- name=pos+1;
- else
- name++;
- #endif
- #ifdef UNIX
- if(name=strrchr(file,'/'))
- name++;
- #endif
- else
- name=file;
- if(!(dfile=malloc(strlen(name)+1))){
- puts(err_no_mem);
- fclose(source);
- exit(EXIT_FAILURE);
- }
- strcpy(dfile,name);
- if(path){
- if(!(dfd=opendir(path))){
- puts(err_bad_dest);
- fclose(source);
- free(dfile);
- exit(EXIT_FAILURE);
- }
- closedir(dfd);
- #ifndef UNIX
- if(i=strlen(path)){
- #ifdef AMIGA
- if(path[--i]=='/' || path[i]==':')
- j=0;
- #else
- if(path[--i]=='\\' || path[i]==':')
- j=0;
- #endif
- else
- j=1;
- }
- else
- j=0;
- if(!(dpath=(char *)malloc(strlen(path)+j+1))){
- puts(err_no_mem);
- fclose(source);
- free(dfile);
- exit(EXIT_FAILURE);
- }
- #ifdef AMIGA
- sprintf(dpath,"%s%s",path,j?"/":"");
- #else
- sprintf(dpath,"%s%s",path,j?"\\":"");
- #endif
- #else
- if(!(dpath=(char *)malloc(strlen(path)+2))){
- puts(err_no_mem);
- fclose(source);
- free(dfile);
- exit(EXIT_FAILURE);
- }
- sprintf(dpath,"%s/",path);
- #endif
- }
- else{
- if(!(dpath=malloc(name-file+1))){
- puts(err_no_mem);
- fclose(source);
- free(dfile);
- exit(EXIT_FAILURE);
- }
- sprintf(dpath,"%.*s",name-file,file);
- }
- if(msdos){
- if(pos=strchr(dfile,'.'))
- pos[0]='\0';
- if(strlen(dfile)>8)
- dfile[8]='\0';
- }
- if(head)
- sprintf(hd.name,"%.*s",hd_namesize-1,name);
- if(!(dbuf=(char *)malloc(strlen(dpath)+strlen(dfile)+5))){
- puts(err_no_mem);
- fclose(source);
- free(dfile);
- free(dpath);
- exit(EXIT_FAILURE);
- }
- if(fseek(source,0L,SEEK_END)){
- puts(err_seek);
- fclose(source);
- free(dfile);
- free(dpath);
- free(dbuf);
- exit(EXIT_FAILURE);
- }
- if(!(tsize=ftell(source))){
- puts(err_file_empty);
- fclose(source);
- free(dfile);
- free(dpath);
- free(dbuf);
- exit(EXIT_FAILURE);
- }
- if(size){
- num=(tsize+size-1)/size;
- size=size<tsize?size:tsize;
- }
- else
- size=(tsize+num-1)/num;
- if(head){
- hd.tsize=tsize;
- hd.tnumber=num;
- }
- if(!(tbuf=(char *)malloc(csize=size))){
- while(csize>10000 && !tbuf)
- tbuf=(char *)malloc(csize=(csize+1)/2);
- if(!tbuf){
- puts(err_no_mem);
- fclose(source);
- free(dfile);
- free(dpath);
- free(dbuf);
- exit(EXIT_FAILURE);
- }
- }
- cnum=(size+csize-1)/csize;
- if(rstart){
- i=rstart;
- if(!rend)
- rend=rstart;
- if(rend>num || rstart>rend){
- puts(err_bad_range);
- fclose(source);
- free(dfile);
- free(dpath);
- free(dbuf);
- free(tbuf);
- exit(EXIT_FAILURE);
- }
- }
- else{
- i=1;
- rend=num;
- }
- if(fseek(source,(i-1)*size,SEEK_SET)){
- puts(err_seek);
- fclose(source);
- free(dfile);
- free(dpath);
- free(dbuf);
- free(tbuf);
- exit(EXIT_FAILURE);
- }
- for(rsize=tsize+(2-i)*size;i<=rend;i++){
- rsize-=size;
- asize=(rsize<size?rsize:size);
- if(head){
- hd.number=i;
- hd.size=asize;
- }
- sprintf(dbuf,"%s%s.%03d",dpath,dfile,i);
- if(query && (dest=fopen(dbuf,"rb"))){
- fclose(dest);
- printf(query_overwrite_a,dbuf);
- gets(buf);
- if(buf[0]==query_all)
- query=0;
- else if(buf[0]!=query_yes){
- puts(err_write_abort);
- fclose(source);
- free(dfile);
- free(dpath);
- free(dbuf);
- free(tbuf);
- exit(EXIT_FAILURE);
- }
- }
- if(multi){
- puts(make_multi_part);
- gets(buf);
- }
- if(!(dest=fopen(dbuf,"wb"))){
- printf(err_open_dest "\n",dbuf);
- fclose(source);
- free(dfile);
- free(dpath);
- free(dbuf);
- free(tbuf);
- exit(EXIT_FAILURE);
- }
- if(head && WriteHead(dest,&hd)){
- puts(err_write_head);
- fclose(dest);
- fclose(source);
- free(dfile);
- free(dpath);
- free(dbuf);
- free(tbuf);
- exit(EXIT_FAILURE);
- }
- for(rcsize=asize+csize,j=0;j<cnum;j++){
- rcsize-=csize;
- acsize=(rcsize<csize?rcsize:csize);
- if(fread(tbuf,1,acsize,source)!=acsize){
- puts(err_read);
- fclose(dest);
- fclose(source);
- free(dfile);
- free(dpath);
- free(dbuf);
- free(tbuf);
- exit(EXIT_FAILURE);
- }
- if(fwrite(tbuf,1,acsize,dest)!=acsize){
- puts(err_write);
- fclose(dest);
- fclose(source);
- free(dfile);
- free(dpath);
- free(dbuf);
- free(tbuf);
- exit(EXIT_FAILURE);
- }
- }
- fclose(dest);
- }
- fclose(source);
- free(tbuf);
- free(dbuf);
- free(dpath);
- free(dfile);
- i=head?hd_size:0;
- printf(split_Splitted,file);
- if(num-1)
- if(num*size==tsize)
- printf(split_portions "\n",num,size+i);
- else
- if(num-2)
- printf(split_portions_and "\n",num-1,size+i,rsize+i);
- else
- printf(split_portion_and "\n",size+i,rsize+i);
- else
- printf(split_portion "\n",rsize+i);
- if(rstart)
- if(rstart!=rend)
- printf(split_Extract "\n",rstart,rend);
- else
- printf(split_Extract_one "\n",rstart);
- exit(0);
- }
-
- /*
- main(int argc,char *argv[])
- argc: Number of arguments.
- argv: Array of arguments.
- Global:
- msdos: -set- Filenames use msdos compatible format.
- head: -set- Use headers.
- multi: -set- Use multiple volumes.
- query: -set- Ask before overwriting existing file.
- rstart: -set- First protion to extract.
- rend: -set- Last Portion to extract.
- Calls:
- Split: Split a file.
- Join: Join splitted parts.
- In main() the arguments are parsed and the appropriate functions
- are called. When calling Join(), 'paths' is not freed.
- */
- void main(int argc,char **argv)
- {
- int i,j,action,pathnum,portnum,defj;
- unsigned long portsize;
- char *arg,*path,*file,**paths;
- #ifdef DBUG
- printf("\nmain(%d,({",argc);
- for(i=0;i<argc-1;i++)
- printf("\"%s\",",argv[i]);
- printf("\"%s\"",argv[i]);
- puts("}));");
- #endif
- if(argc==1){
- printf(err_no_args "\n",argv[0]);
- exit(EXIT_FAILURE);
- }
- if(!(paths=(char **)malloc((argc-1)*sizeof(char *)))){
- puts(err_no_mem);
- exit(EXIT_FAILURE);
- }
- #ifdef MSDOS
- msdos=1;
- #else
- msdos=0;
- #endif
- pathnum=rstart=rend=portnum=0;
- portsize=0;
- head=1;
- #if FORCE
- query=0;
- #else
- query=1;
- #endif
- if(strstr(argv[0],"Join") || strstr(argv[0],"join"))
- action=defj=1;
- else
- action=defj=0;
- if(strchr(argv[0],'M') || strchr(argv[0],'m'))
- multi=1;
- else
- multi=0;
- for(i=1;i<argc;i++){
- arg=argv[i];
- if('-'==*arg)
- while(*++arg)
- switch(*arg){
- case 'h':
- if(defj)
- printf(info1j,argv[0]);
- else{
- printf(info1s,argv[0]);
- getchar();
- puts(info2);
- for(j=0;j<sizeof(fs)/sizeof(struct fs_item);j++)
- printf(main_fs "\n",fs[j].name,fs[j].size,fs[j].desc);
- }
- puts(main_end);
- free(paths);
- exit(0);
- case 'j':
- action=1;
- break;
- case 's':
- action=2;
- if(!*++arg){
- if(i==argc-1){
- puts(err_bad_size);
- free(paths);
- exit(EXIT_FAILURE);
- }
- arg=argv[++i];
- }
- for(j=0;j<sizeof(fs)/sizeof(struct fs_item);j++)
- if(!strcmp(arg,fs[j].name))
- portsize=fs[j].size;
- if(!portsize){
- if(!(portsize=atol(arg))){
- puts(err_bad_size);
- free(paths);
- exit(EXIT_FAILURE);
- }
- if(strchr(arg,'k'))
- portsize*=1024;
- if(strchr(arg,'m'))
- portsize*=1024*1024;
- }
- *arg--=0;
- break;
- case 'p':
- action=3;
- if(!*++arg){
- if(i==argc-1){
- puts(err_bad_num);
- free(paths);
- exit(EXIT_FAILURE);
- }
- arg=argv[++i];
- }
- if(!(portnum=atoi(arg))){
- puts(err_bad_num);
- free(paths);
- exit(EXIT_FAILURE);
- }
- *arg--=0;
- break;
- case 'r':
- if(!*++arg){
- if(i==argc-1){
- puts(err_bad_range);
- free(paths);
- exit(EXIT_FAILURE);
- }
- arg=argv[++i];
- }
- if(!(rstart=atoi(arg))){
- puts(err_bad_range);
- free(paths);
- exit(EXIT_FAILURE);
- }
- if(i<argc-1 && !(rend=atoi(argv[++i])))
- --i;
- *arg--=0;
- break;
- case 'd':
- msdos=1;
- break;
- case 'l':
- msdos=0;
- break;
- case 'n':
- head=0;
- break;
- case 'm':
- multi=1;
- break;
- case 'g':
- multi=0;
- break;
- case 'f':
- query=0;
- break;
- case 'q':
- query=1;
- break;
- default:
- printf(err_unknown_option "\n",*arg);
- free(paths);
- exit(EXIT_FAILURE);
- }
- else
- paths[pathnum++]=arg;
- }
- if(!pathnum--){
- puts(err_no_file);
- free(paths);
- exit(EXIT_FAILURE);
- }
- if(action!=1){
- file=paths[0];
- if(pathnum)
- path=paths[1];
- else
- path=0;
- free(paths);
- }
- switch(action){
- case 1:
- Join(paths[pathnum],paths,pathnum);
- case 2:
- Split(file,path,0,portsize);
- case 3:
- Split(file,path,portnum,0);
- default:
- Split(file,path,0,fs[0].size);
- }
- }
-